﻿using System;
using System.Collections.Generic;
using System.Text;

namespace AppMain
{
    public class RoleSyncControl : BaseControl
    {

        public override void initialize()
        {

        }

        public override void initEventListener()
        {
            ProtocolEventMgr.Instance.addListener(Cmd.RoleMoveReqMsg, onRoleMove);
            ProtocolEventMgr.Instance.addListener(Cmd.RoleActionMsg, onRoleActionMsg);
            ProtocolEventMgr.Instance.addListener(Cmd.RoleEnterSceneReqMsg, onRoleEnterSceneReqMsg);
            ProtocolEventMgr.Instance.addListener(Cmd.RoleEnterSceneFinishReqMsg, onRoleEnterSceneFinishReqMsg);
            ProtocolEventMgr.Instance.addListener(Cmd.ChatReqMsg, onChatReqMsg);
            ProtocolEventMgr.Instance.addListener(Cmd.AttackMsg, onAttackMsg);

            EventMgr.Instance.addListener(EventCmd.Entity_Enter_Trigger, onEntity_Enter_Trigger);
            EventMgr.Instance.addListener(EventCmd.Role_Attack_Event, onRole_Attack_Event);
        }

        private void onRole_Attack_Event(Message msg)
        {
            long sourceId = (long)msg[0];
            long targetId = (long)msg[1];
            int actionId = (int)msg[2];
            int hitId = (int)msg[3];

            NetRole sourceRole = RoleMgr.Instance.getRole<NetRole>(sourceId);
            ActionRole baseRole = RoleMgr.Instance.getRole<ActionRole>(targetId);
            BaseScene baseScene = baseRole.AttrMap.getAttr<BaseScene>(RoleAttr.Scene).Value;// SceneMgr.Instance.getScene<BaseScene>(baseRole.sceneId);
            int nowHp = baseRole.AttrMap.getAttr<int>(RoleAttr.NowHp).Value;
            Random random = new Random();
            int ran = random.Next(10, 150);
            ran = ran > nowHp ? nowHp : ran;
            nowHp -= ran;
            baseRole.AttrMap.changeAttr(RoleAttr.NowHp, nowHp);

            //广播客户端 受击表现
            pb.DamageMsg damage = new pb.DamageMsg();
            damage.roleId = baseRole.UID;
            damage.damageValue = ran;
            damage.leftValue = nowHp;
            damage.acitonId = actionId;
            damage.hitId = hitId;
            damage.dir = new pb.PBVector3();
            damage.dir.x = baseRole.box3D.posX - sourceRole.box3D.posX;
            damage.dir.y = baseRole.box3D.posY - sourceRole.box3D.posY;
            damage.dir.z = baseRole.box3D.posZ - sourceRole.box3D.posZ;
            damage.pos = new pb.PBVector3();
            damage.pos.x = baseRole.box3D.posX;
            damage.pos.y = baseRole.box3D.posY;
            damage.pos.z = baseRole.box3D.posZ;
            damage.roleMoveStatus = (int)baseRole.moveWidget.getRoleMoveStatus();
            baseScene.broadCast(Cmd.DamageMsg, damage);

            //服务器 受击表现
            DamageData damageData = new DamageData();
            damageData.roleId = baseRole.UID;
            damageData.hitId = hitId;
            float[] normalizeDir = MathUtils.Normalize(damage.dir.x * 0.001f, 0, 0);
            damageData.dir = new Vec3();
            damageData.dir.x = normalizeDir[0];
            //damageData.z = normalizeDir[2];
            baseRole.addAction(ActionCreator.createAction(hitId, damageData));
        }

        private void onAttackMsg(NetRole role, PBMessage pbs)
        {
            pb.AttackMsg attackMsg = pb.ProtobufSerializer.DeSerialize<pb.AttackMsg>(pbs.data);
            long sourceId = attackMsg.sourceId;
            List<long> lst = attackMsg.targets;
            BoxRole sourceRole = RoleMgr.Instance.getRole<BoxRole>(sourceId);
            for (int i = 0; i < lst.Count; i++)
            {
                long targetId = lst[i];
                ActionRole baseRole = RoleMgr.Instance.getRole<ActionRole>(targetId);
                BaseScene baseScene = baseRole.AttrMap.getAttr<BaseScene>(RoleAttr.Scene).Value;// SceneMgr.Instance.getScene<BaseScene>(baseRole.sceneId);
                int nowHp = baseRole.AttrMap.getAttr<int>(RoleAttr.NowHp).Value;
                Random random = new Random();
                int ran = random.Next(10, 150);
                ran = ran > nowHp ? nowHp : ran;
                nowHp -= ran;
                baseRole.AttrMap.changeAttr(RoleAttr.NowHp, nowHp);

                pb.DamageMsg damage = new pb.DamageMsg();
                damage.roleId = baseRole.UID;
                damage.damageValue = ran;
                damage.leftValue = nowHp;
                damage.acitonId = attackMsg.actionId;
                damage.hitId = attackMsg.hitId;
                damage.dir = new pb.PBVector3();
                damage.dir.x = baseRole.box3D.posX - sourceRole.box3D.posX;
                damage.dir.y = baseRole.box3D.posY - sourceRole.box3D.posY;
                damage.dir.z = baseRole.box3D.posZ - sourceRole.box3D.posZ;
                damage.pos = new pb.PBVector3();
                damage.pos.x = baseRole.box3D.posX;
                damage.pos.y = baseRole.box3D.posY;
                damage.pos.z = baseRole.box3D.posZ;
                damage.roleMoveStatus = (int)baseRole.moveWidget.getRoleMoveStatus();
                baseScene.broadCast(Cmd.DamageMsg, damage);

                DamageData damageData = new DamageData();
                damageData.roleId = baseRole.UID;
                damageData.hitId = attackMsg.hitId;
                float[] normalizeDir = MathUtils.Normalize(damage.dir.x, 0, 0);
                damageData.dir = new Vec3();
                damageData.dir.x = normalizeDir[0];
                //damageData.z = normalizeDir[2];
                baseRole.addAction(ActionCreator.createAction(attackMsg.hitId, damageData));
            }
        }



        private void onChatReqMsg(NetRole role, PBMessage pbs)
        {
            pb.ChatReqMsg msg = pb.ProtobufSerializer.DeSerialize<pb.ChatReqMsg>(pbs.data);
            long copyUID = role.AttrMap.getAttr<long>(RoleAttr.CopySceneUID).Value;
            long sceneId = role.AttrMap.getAttr<long>(RoleAttr.SceneId).Value;
            long sceneUID = copyUID > 0 ? copyUID : sceneId;
            BaseScene baseScene = SceneMgr.Instance.getScene<BaseScene>(sceneUID);
            if (baseScene != null)
            {
                pb.ChatRespMsg rtn = new pb.ChatRespMsg();
                rtn.roleId = role.UID;
                rtn.roleName = role.AttrMap.getAttr<string>(RoleAttr.NickName).Value;
                rtn.channel = 1;
                rtn.content = msg.content;
                baseScene.broadCast(Cmd.ChatRespMsg, rtn);
            }
        }

        private void onEntity_Enter_Trigger(Message msg)
        {
            NetRole role = (NetRole)msg[0];
            long sceneId = (long)msg[1];
            long copyUID = role.AttrMap.getAttr<long>(RoleAttr.CopySceneUID).Value;
            long currsceneId = role.AttrMap.getAttr<long>(RoleAttr.SceneId).Value;
            long sceneUID = copyUID > 0 ? copyUID : currsceneId;
            BaseScene baseScene = SceneMgr.Instance.getScene<BaseScene>(sceneUID);
            if (baseScene != null)
            {
                pb.ChatRespMsg rtn = new pb.ChatRespMsg();
                rtn.roleId = role.UID;
                rtn.roleName = "系统";
                rtn.channel = 1;
                rtn.content = string.Format("玩家【{0}】踩到了服务器触发器", role.AttrMap.getAttr<string>(RoleAttr.NickName).Value);
                baseScene.broadCast(Cmd.ChatRespMsg, rtn);
            }
            changeRoleScene(role, sceneId);
        }

        private void onRoleEnterSceneFinishReqMsg(NetRole role, PBMessage pbs)
        {
            Console.WriteLine("玩家加载场景完毕");
            role.RoleStatus = Role_Status.None;
            SceneMgr.Instance.roleEnterWorld(role);
            //同步一下出生点位置
            pb.RoleMoveBroadCastMsg rtn2 = new pb.RoleMoveBroadCastMsg();
            rtn2.roleId = role.UID;
            rtn2.status = 9;//状态9位置同步 强行切位置
            rtn2.posx = role.box3D.posX;
            rtn2.posy = role.box3D.posY;
            rtn2.posz = role.box3D.posZ;
            role.send(Cmd.RoleMoveBroadCastMsg, rtn2);
        }

        private void onRoleEnterSceneReqMsg(NetRole role, PBMessage pbs)
        {
            pb.RoleEnterSceneReqMsg msg = pb.ProtobufSerializer.DeSerialize<pb.RoleEnterSceneReqMsg>(pbs.data);
            int sceneId = msg.sceneId;
            int roomId = msg.roomId;
            changeRoleScene(role, sceneId, roomId);
        }

        private void changeRoleScene(NetRole role, long sceneId, int roomId = 0)
        {
            if (role == null) return;
            long roleId = role.UID;
            //写入sql 玩家离线会被写入            
            //先从上个场景移除
            SceneMgr.Instance.removeRole(role);
            //再从进入下个场景
            float x = -1, y = -1, z = -1;
            string sceneSql = string.Format("select *from tb_scene_temp where id='{0}'", sceneId);
            var sceneReader = SqlMgr.Instance.select(sceneSql);
            if (sceneReader.Read())
            {
                x = (float)sceneReader[2];
                y = (float)sceneReader[3];
                z = (float)sceneReader[4];
            }
            sceneReader.Close();
            role.box3D.updatePos(x, y, z);
            Console.WriteLine(string.Format("修改玩家出生点位置 roleId:{0}  sceneId:{1} ", roleId, sceneId));
            role.AttrMap.changeAttr(RoleAttr.SceneId, sceneId);
            //同步玩家
            role.RoleStatus = Role_Status.LoadingMap;
            pb.RoleEnterSceneRepsMsg rtn = new pb.RoleEnterSceneRepsMsg();
            rtn.roleId = roleId;
            rtn.sceneId = sceneId;
            rtn.roomId = roomId;
            role.send(Cmd.RoleEnterSceneRepsMsg, rtn);
        }

        private void onRoleActionMsg(NetRole role, PBMessage pbs)
        {
            pb.RoleActionMsg msg = pb.ProtobufSerializer.DeSerialize<pb.RoleActionMsg>(pbs.data);
            long copyUID = role.AttrMap.getAttr<long>(RoleAttr.CopySceneUID).Value;
            long sceneId = role.AttrMap.getAttr<long>(RoleAttr.SceneId).Value;
            long sceneUID = copyUID > 0 ? copyUID : sceneId;
            BaseScene baseScene = SceneMgr.Instance.getScene<BaseScene>(sceneUID);
            Console.WriteLine("收到玩家攻击消息  msg.actionId : " + msg.actionId);
            if (baseScene != null)
            {
                //广播技能消息
                pb.RoleActionBroadMsg rtn = new pb.RoleActionBroadMsg();
                rtn.roleId = role.UID;
                rtn.actionId = msg.actionId;
                rtn.posx = role.box3D.posX;
                rtn.posy = role.box3D.posY;
                rtn.posz = role.box3D.posZ;
                baseScene.broadCast(Cmd.RoleActionBroadMsg, rtn);
                role.addAction(ActionCreator.createAction(msg.actionId));
            }
        }

        private void onRoleMove(NetRole role, PBMessage pbs)
        {
            if (role.RoleStatus == Role_Status.LoadingMap) return;
            pb.RoleMoveReqMsg msg = pb.ProtobufSerializer.DeSerialize<pb.RoleMoveReqMsg>(pbs.data);
            //设置自己的当前位置 并且广播
            role.box3D.updatePos(msg.posx, msg.posy, msg.posz);
            if (msg.status != 0)
                role.AttrMap.changeAttr<int>(RoleAttr.LookFlag, msg.status);
            long copyUID = role.AttrMap.getAttr<long>(RoleAttr.CopySceneUID).Value;
            long sceneId = role.AttrMap.getAttr<long>(RoleAttr.SceneId).Value;
            long sceneUID = copyUID > 0 ? copyUID : sceneId;
            BaseScene baseScene = role.AttrMap.getAttr<BaseScene>(RoleAttr.Scene).Value;// SceneMgr.Instance.getScene<BaseScene>(sceneUID);
            if (baseScene != null)
            {
                pb.RoleMoveBroadCastMsg rtn = new pb.RoleMoveBroadCastMsg();
                rtn.roleId = role.UID;
                rtn.status = msg.status;
                rtn.posx = role.box3D.posX;
                rtn.posy = role.box3D.posY;
                rtn.posz = role.box3D.posZ;
                rtn.dirx = msg.dirx;
                rtn.dirz = msg.dirz;
                baseScene.broadCast(Cmd.RoleMoveBroadCastMsg, rtn);
            }
        }

        public override void onDispose()
        {

        }
    }
}
